///////////////////////////////////////////////////////////////////////////////
//
// Licensed under the MIT License
//
// Copyright (c) 2010 Chris Colinsky
// All Rights Reserved
//
// version	0.5
// http://code.google.com/p/sugarcookie/
// http://code.google.com/p/sugarcookie/wiki/License
//
////////////////////////////////////////////////////////////////////////////////

package sugarcookie.ui {
	import com.greensock.*;
	import com.greensock.easing.*;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;

	public class BasicScrollBar extends Sprite {
		protected var _up_arrow:Sprite;
		protected var _down_arrow:Sprite;
		protected var _scroll_track_bg:Sprite;
		protected var _scrubber:Sprite;
		
		private var _so:DisplayObject;
		private var _msk:Sprite;
		private var _startY:Number;
		private var _dir:String;
		private var _dist:Number;
		private var _scrubStartY:Number;
		private var _scrubHeight:Number;
		private var _scrubDist:Number;
		private var _useArrows:Boolean;
		private var _fixedScrubberHeigth:Boolean;
		
		public function BasicScrollBar(scrollableObj:DisplayObject,msk:Sprite,useArrows:Boolean=true,fixedScrubberSize:Boolean=false) {
			super();
			
			_so = scrollableObj;
			_startY = _so.y;
			_msk = msk;
			_useArrows = useArrows;
			_fixedScrubberHeigth = fixedScrubberSize;
			assignGraphics()
			init();
		}
		
		protected function assignGraphics():void {
			
		}
		
		public function updateScollableHeight(updatedHeight:Number=-1):void {
			if (updatedHeight==-1) updatedHeight = _so.height;
			
			if (updatedHeight<_msk.height) {
				TweenMax.to(this,.3,{autoAlpha:0,ease:Quad.easeOut});
				return;
			} else {
				TweenMax.to(this,.3,{autoAlpha:1,ease:Quad.easeOut});
			}
			
			_so.y = _startY;
			TweenMax.to(_scrubber,.2,{y:_scrubStartY,ease:Quad.easeOut});
			
			_dist = int(updatedHeight - (_msk.height - (_so.y - _msk.y)));
			if (!_fixedScrubberHeigth) {
				var newHeight:Number = _scrubHeight* (1-(_dist/updatedHeight));
				TweenMax.to(_scrubber,.2,{height:newHeight,ease:Quad.easeOut});
				_scrubDist = _scrubHeight - newHeight;
			} else {
				_scrubDist = _scroll_track_bg.height - _scrubber.height;
			}
		}
		
		private function init():void {
			if (_useArrows) {
				_up_arrow.mouseChildren = false;
				_up_arrow.buttonMode = true;
				_up_arrow.addEventListener(MouseEvent.MOUSE_DOWN,mousedown);
				_up_arrow.addEventListener(MouseEvent.MOUSE_UP,mouseup);
				
				_down_arrow.mouseChildren = false;
				_down_arrow.buttonMode = true;
				_down_arrow.addEventListener(MouseEvent.MOUSE_DOWN,mousedown);
				_down_arrow.addEventListener(MouseEvent.MOUSE_UP,mouseup);
			}
			
			_scrubStartY = _scrubber.y;
			_scrubHeight = _scrubber.height;
			_scrubber.buttonMode = true;
			_scrubber.mouseChildren = false;
			_scrubber.addEventListener(MouseEvent.MOUSE_DOWN,scrubdown);
			updateScollableHeight();
		}
		
		private function enterFrame(evt:Event):void {
			TweenMax.killTweensOf(_so);
			TweenMax.killTweensOf(_scrubber);
			switch (_dir) {
				case "up":
					if (_so.y == _startY) return;
					if (_so.y < _startY) {
						TweenMax.to(_so,.3,{y:"25",ease:Quad.easeOut,onUpdate:updateScrollerPos});
					} else if (_so.y > _startY) {
						_so.y = _startY;
						_scrubber.y = _scrubStartY;
						removeEventListener(Event.ENTER_FRAME,enterFrame);
					}
					break;
				case "down":
					if (_so.y == _startY - _dist) return;
					if (_so.y > _startY - _dist) {
						TweenMax.to(_so,.3,{y:"-25",ease:Quad.easeOut,onUpdate:updateScrollerPos});
					} else if (_so.y < _startY - _dist) {
						_so.y = _startY - _dist;
						_scrubber.y = _scrubStartY + _scrubDist;
						removeEventListener(Event.ENTER_FRAME,enterFrame);
					}
					break;
			}
		}
		
		private function updateScrollerPos():void {
			var perc:Number = (_startY-_so.y)/_dist;
			var newY:Number = _scrubStartY + (_scrubDist*perc);
			_scrubber.y = newY;
		}
		
		private function scrubEnterFrame(evt:Event):void {
			var perc:Number = (_scrubber.y - _scrubStartY)/_scrubDist;
			var newY:Number = _startY - (_dist * perc);
			TweenMax.killTweensOf(_so);
			TweenMax.to(_so,.3,{y:newY,ease:Quad.easeOut});
		}
		
		private function scrubdown(evt:MouseEvent):void {
			_scrubber.removeEventListener(MouseEvent.MOUSE_DOWN,scrubdown);
			_scrubber.addEventListener(MouseEvent.MOUSE_UP,scrubup);
			stage.addEventListener(MouseEvent.MOUSE_UP,scrubup);
			addEventListener(Event.ENTER_FRAME,scrubEnterFrame);
			_scrubber.startDrag(false,new Rectangle(_scrubber.x,_scrubStartY,0,_scrubDist+1));
		}
		
		private function scrubup(evt:MouseEvent):void {
			_scrubber.stopDrag();
			_scrubber.addEventListener(MouseEvent.MOUSE_DOWN,scrubdown);
			_scrubber.removeEventListener(MouseEvent.MOUSE_UP,scrubup);
			stage.removeEventListener(MouseEvent.MOUSE_UP,scrubup);
			removeEventListener(Event.ENTER_FRAME,scrubEnterFrame);
		}
		
		private function mousedown(evt:MouseEvent):void {
			if (evt.target==_up_arrow) _dir = "up";
			else if (evt.target==_down_arrow) _dir = "down";
			addEventListener(Event.ENTER_FRAME,enterFrame);
		}
		
		private function mouseup(evt:MouseEvent):void {
			if (hasEventListener(Event.ENTER_FRAME)) removeEventListener(Event.ENTER_FRAME,enterFrame);
		}
	}
}